package com.shaoyu.tools.event.core;

import com.google.common.base.Preconditions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;
import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;

/**
 * @Desc :
 * @Author: shaoyu
 * @Date : 2022/11/2 10:57
 */
public class SubscribeInterceptor {

    private ExecutorService executor;
    private Object target;
    private Method interceptorMethod;
    private Logger logger = LoggerFactory.getLogger(SubscribeInterceptor.class);

    public static SubscribeInterceptor create(ExecutorService executor, Object target, Method method) {
        return new SubscribeInterceptor(executor, target, method);
    }

    public SubscribeInterceptor(ExecutorService executor, Object target, Method interceptorMethod) {
        this.executor = executor;
        this.target = target;
        this.interceptorMethod = interceptorMethod;
    }

    public final Future<Boolean> dispatchEvent(final Object event) {
        Preconditions.checkNotNull(event);
        Callable<Boolean> callable = () -> {
            try{
                Object pass = interceptorMethod.invoke(target, event);
                if (!(Boolean) pass) {
                    logger.warn("event[{}]had been intercepted in Subscribe Interceptor[{}#{}]!", event.getClass().getSimpleName(),
                            target.getClass().getName(), interceptorMethod.getName());
                    return false;
                }
            }catch (Exception e){
                logger.error("拦截器[{}#{}]执行出错:{}",target.getClass().getName(), interceptorMethod.getName(),e);
            }
            return true;
        };
        return this.executor.submit(callable);
    }

    @Override
    public final int hashCode() {
        return (31 + this.interceptorMethod.hashCode()) * 31 + System.identityHashCode(this.target);
    }

    @Override
    public final boolean equals(Object obj) {
        if (Objects.isNull(obj)) return false;
        if (!(obj instanceof SubscribeInterceptor)) {
            return false;
        } else {
            SubscribeInterceptor that = (SubscribeInterceptor) obj;
            return this.target == that.target && this.interceptorMethod.equals(that.interceptorMethod);
        }
    }
}
